iT邦幫忙

2022 iThome 鐵人賽

DAY 30
0

今天我們來運用前幾天所學,寫一個計算函式執行時間的函式。

我們希望這個函式可以計算各種奇形怪狀的函式,當然也要能吃下各種引數。

我們的函式 time_it 會有以下的參數:

  • 我們要計算的 function
  • 被計算函式的位置參數
  • 被計算函式的關鍵字參數
  • 我們想要跑這個 function 幾次
import time
def time_it(fn, *args, rep=5, **kwargs):
    print(args, rep, kwargs)

預設我們會跑被計算的 function 五次:

time_it(print, 1, 2, 3, sep='-')
(1, 2, 3) 5 {'sep': '-'}

修改一下:

def time_it(fn, *args, rep=5, **kwargs):
    for i in range(rep):
        fn(*args, **kwargs)
time_it(print, 1, 2, 3, sep='-')
1-2-3
1-2-3
1-2-3
1-2-3
1-2-3

成功把 print 執行五次了,而且 sep 參數用到 '-'。

還可以再加更多引數:

time_it(print, 1, 2, 3, sep='-', end=' *** ', rep=3)
1-2-3 *** 1-2-3 *** 1-2-3 *** 

再修改一下,要真正開始計算時間了:

def time_it(fn, *args, rep=5, **kwargs):
    start = time.perf_counter()
    for i in range(rep):
        fn(*args, **kwargs)
    end = time.perf_counter()
    return (end - start) / rep

OK,現在來寫幾個準備被計算執行時間的函式:

我們寫個函式,列出整數 n 從 start 次方到 end 次方:

def compute_powers_1(n, *, start=1, end):
    # 使用 loop 的版本
    results = []
    for i in range(start, end):
        results.append(n**i)
    return results
def compute_powers_2(n, *, start=1, end):
    # 使用串列生成式的版本
    return [n**i for i in range(start, end)]
def compute_powers_3(n, *, start=1, end):
    # 使用 generator 的版本
    return (n**i for i in range(start, end))

來跑跑看:

compute_powers_1(2, end=5)
[2, 4, 8, 16]
compute_powers_2(2, end=5)
[2, 4, 8, 16]
list(compute_powers_3(2, end=5))
[2, 4, 8, 16]

最後用一開始寫的 time_it 來計算一下時間:

time_it(compute_powers_1, n=2, end=20000, rep=4)
0.3699034999990545
time_it(compute_powers_2, 2, end=20000, rep=4)
0.3647651249993942
time_it(compute_powers_3, 2, end=20000, rep=4)
6.980008038226515e-07

可以看到產生一個 generator 比產生一個陣列快很多。

今年的鐵人賽到此,我們明年見~

參考:Python 3: Deep Dive (Part 1 - Functional)


上一篇
*args, **kwargs 大集合
系列文
小青蛇變大蟒蛇——進階Python學起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言